#include "logicengine.h"
#include "easylogging/easylogging++.h"
#include "QFile"
#include "qjson/parser.h"
#include "qjson/serializer.h"
#include <QVariantMap>
#include "qdebug.h"
#include "QVariantList"
#include "rule_201.h"
#include "ruleformula.h"
#include "crashcollect.h"

_INITIALIZE_EASYLOGGINGPP

using namespace QJson;

LogicEngine::LogicEngine(QString stationName)
{
    CrashCollect::Register();

    ConfigLog();
    Init(stationName);
}

LogicEngine::~LogicEngine()
{
    QMapIterator<int,RuleBase*> it(m_mRules);
        while (it.hasNext()) {
            delete it.value();
            it.next();
        }
}

void LogicEngine::Init(QString stationName)
{
    LDEBUG<<"LogicEngin::Init :" << stationName;
    Load102(stationName);
    Load201(stationName);
    Load202(stationName);
}

QString LogicEngine::CheckLogic(QString content)
{
    QMapIterator<int,RuleBase*> it(m_mRules);
        while (it.hasNext()) {
            it.next();
            if(it.key() == content.toInt())
            {
                RuleResult ruleResult = it.value()->Run(it.value()->GetName());
                if(ruleResult.result)
                {
                    QVariantMap result;
                    result.insert("name",ruleResult.name);
                    Serializer serializer;
                    QString returnMsg = serializer.serialize(result);
                    return  returnMsg;
                }
                else
                {

                }
            }
            qDebug() << it.key() << ":" << it.value();
        }
    return "";
}

void LogicEngine::UpdateDeviceState(QString content)
{
}

void LogicEngine::ConfigLog()
{
    setvbuf(stdout, NULL, _IOLBF, 0);
    easyloggingpp::Configurations defaultConf;
    defaultConf.setToDefault();
    defaultConf.setAll(easyloggingpp::ConfigurationType::Format, " %datetime %level [%loc] %log");
    defaultConf.setAll(easyloggingpp::ConfigurationType::Filename,"./log/logicengine.log");
    defaultConf.setAll(easyloggingpp::ConfigurationType::ToFile,"true");
    defaultConf.setAll(easyloggingpp::ConfigurationType::ToStandardOutput,"true");
    defaultConf.setAll(easyloggingpp::ConfigurationType::Enabled,"true");
    defaultConf.setAll(easyloggingpp::ConfigurationType::MillisecondsWidth,"3");
    defaultConf.setAll(easyloggingpp::ConfigurationType::PerformanceTracking,"false");
    defaultConf.setAll(easyloggingpp::ConfigurationType::RollOutSize,"52428800"); //50M
    easyloggingpp::Loggers::reconfigureAllLoggers(defaultConf);
}

void LogicEngine::Load102(QString stationName)
{
    QString stationRuleFileName = "./" + stationName + "_102_rule.txt";
    QFile stationfile(stationRuleFileName);
    if(!stationfile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        LDEBUG<<"have no "<<stationRuleFileName;
    }
    else
    {
        LDEBUG<<"open "<<stationRuleFileName + " success";
    }

    QFile file("./Basic_102_rule.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        LDEBUG<<"can't open Basic_102_rule.txt";
        return;
    }

    LDEBUG<<"open Basic_102_rule.txt success";
}

void LogicEngine::Load201(QString stationName)
{
    QString stationRuleFileName = "./" + stationName + "_201_rule.txt";
    QFile stationfile(stationRuleFileName);
    if(!stationfile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        LDEBUG<<"have no "<<stationRuleFileName;
    }
    else
    {
        LDEBUG<<"open "<<stationRuleFileName + " success";
    }

    bool success = true;
    QJson::Parser parser;
    QVariantMap totalcoutent = parser.parse(stationfile.readAll(),&success).toMap();
    if(success == true)
    {
        QVariantList rulelist = totalcoutent.value("root").toList();
        for(int i = 0; i < rulelist.size(); i++)
        {
            Rule_201* rule = new Rule_201();
            QVariantMap oneRule = rulelist[i].toMap();
            rule->SetRuleID(oneRule.value("id").toInt());
            rule->SetName(oneRule.value("name").toString());

            QVariantList conditionlist = oneRule.value("conditions").toList();
            for(int i = 0; i < conditionlist.size(); i++)
            {
                Condition* condition = new Condition();
                QVariantMap onecondition = conditionlist[i].toMap();
                condition->SetName(onecondition.value("name").toString());
                condition->SetType(onecondition.value("protect").toString());
                condition->SetArgName(onecondition.value("arg").toString());
                condition->SetFormula(onecondition.value("formula").toString());

                QVariantList entitylist = onecondition.value("entitys").toList();
                for(int i = 0; i < entitylist.size(); i++)
                {
                    QVariantMap oneEntity = entitylist[i].toMap();
                    condition->AddEntity(new Entity(oneEntity.value("entity").toString(),
                                                    oneEntity.value("runningstate").toInt(),
                                                    oneEntity.value("locktype").toString(),
                                                    oneEntity.value("arg").toString()));
                }

                rule->AddConditon(condition);
            }

            QVariantList formulaslist = oneRule.value("formulas").toList();
            for(int i = 0; i < formulaslist.size(); i++)
            {
                QVariantMap oneformula = formulaslist[i].toMap();
                rule->AddFormula(new RuleFormula(oneformula.value("name").toString(),
                                                 oneformula.value("formula").toString()));
            }

            m_mRules.insert(rule->GetRuleID(),rule);
        }
    }
    else
    {
        LDEBUG<<stationRuleFileName + "json parserfail";
    }

    QFile file("./Basic_201_rule.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        LDEBUG<<"can't open Basic_201_rule.txt";
        return;
    }

    LDEBUG<<"open Basic_201_rule.txt success";

    QVariantMap basiccoutent = parser.parse(stationfile.readAll(),&success).toMap();
    if(success == true)
    {
        QVariantList rulelist = basiccoutent.value("root").toList();
        for(int i = 0; i < rulelist.size(); i++)
        {
            Rule_201* rule = new Rule_201();
            QVariantMap oneRule = rulelist[i].toMap();
            int ruleID = oneRule.value("id").toInt();
            if(m_mRules.contains(ruleID))
            {
                continue;
            }
            rule->SetRuleID(ruleID);
            rule->SetName(oneRule.value("name").toString());

            QVariantList conditionlist = oneRule.value("conditions").toList();
            for(int i = 0; i < conditionlist.size(); i++)
            {
                Condition* condition = new Condition();
                QVariantMap onecondition = conditionlist[i].toMap();
                condition->SetName(onecondition.value("name").toString());
                condition->SetType(onecondition.value("protect").toString());
                condition->SetArgName(onecondition.value("arg").toString());
                condition->SetFormula(onecondition.value("formula").toString());

                QVariantList entitylist = onecondition.value("entitys").toList();
                for(int i = 0; i < entitylist.size(); i++)
                {
                    QVariantMap oneEntity = entitylist[i].toMap();
                    condition->AddEntity(new Entity(oneEntity.value("entity").toString(),
                                                    oneEntity.value("runningstate").toInt(),
                                                    oneEntity.value("locktype").toString(),
                                                    oneEntity.value("arg").toString()));
                }
            }

            QVariantList formulaslist = oneRule.value("formulas").toList();
            for(int i = 0; i < formulaslist.size(); i++)
            {
                QVariantMap oneformula = formulaslist[i].toMap();
                rule->AddFormula(new RuleFormula(oneformula.value("name").toString(),
                                                 oneformula.value("formula").toString()));
            }

            m_mRules.insert(rule->GetRuleID(),rule);
        }
    }
    else
    {
        LDEBUG<<stationRuleFileName + "json parserfail";
    }

    LDEBUG<<"Load201 finish";
}

void LogicEngine::Load202(QString stationName)
{
    QString stationRuleFileName = "./" + stationName + "_202_rule.txt";
    QFile stationfile(stationRuleFileName);
    if(!stationfile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        LDEBUG<<"have no "<<stationRuleFileName;
    }
    else
    {
        LDEBUG<<"open "<<stationRuleFileName + " success";
    }

    QFile file("./Basic_202_rule.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        LDEBUG<<"can't open Basic_202_rule.txt";
        return;
    }

    LDEBUG<<"open Basic_202_rule.txt success";
}
